#include "user_key.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "stdio.h"
#include "esp_system.h"
#include "esp_timer.h"

#define GPIO_INPUT_IO_0      22
#define GPIO_INPUT_IO_1      26
#define GPIO_INPUT_PIN_SEL   ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT 0


static QueueHandle_t gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}

static void key_handle_task(void* arg)
{
    printf("%s %d start\r\n",__func__, __LINE__);
    while (1) {
    	
		if (key_event.head != key_event.tail)
		{
			if(key_event.key[key_event.head].value == 1)
			{
				printf("%s %d head:%d gpio:%d key is press %lu\r\n",__func__, __LINE__,key_event.head, key_event.key[key_event.head].gpio, key_event.key[key_event.head].tick);
				
			}
			if(key_event.key[key_event.head].value == 1 && key_event.key[key_event.head].gpio == 22)
            {
                printf("key is pressed\r\n");
                PS_Sleep();
            }

			key_event.head = (key_event.head + 1) % KEY_EVENT_MAX;
		}
		vTaskDelay(10);
    }
}

static void gpio_task_example(void* arg)
{
    uint32_t io_num;
    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            printf("GPIO[%lu] intr, val: %d %llu\n", io_num, gpio_get_level(io_num), esp_timer_get_time());
			key_event.key[key_event.tail].value = gpio_get_level(io_num);
			key_event.key[key_event.tail].gpio = io_num;
			key_event.key[key_event.tail].tick = esp_timer_get_time();
			key_event.tail = (key_event.tail + 1) % KEY_EVENT_MAX;
        }
    }
}

void user_key_init(void)
{
    //zero-initialize the config structure.
    gpio_config_t io_conf = {};
    //interrupt of rising edge
    io_conf.intr_type = GPIO_INTR_POSEDGE;
    //bit mask of the pins, use GPIO4/5 here
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    //set as input mode
    io_conf.mode = GPIO_MODE_INPUT;
    //enable pull-up mode
    io_conf.pull_up_en = 1;
    gpio_config(&io_conf);

    //change gpio interrupt type for one pin
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
    gpio_set_intr_type(GPIO_INPUT_IO_1, GPIO_INTR_ANYEDGE);

    //create a queue to handle gpio event from isr
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));

}

void user_key_task(void *arg)
{
    user_key_init();
    printf("%s %d start\r\n",__func__, __LINE__);
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
    xTaskCreate(key_handle_task, "key_handle_task", 2048, NULL, 10, NULL);
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
    gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);

    while (1) {
		vTaskDelay(10);
    }
}
